package servlet;

import controller.ControllerMailLocal;
import controller.ControllerProfiloLocal;
import controller.ControllerUserRegistrationLocal;
import controller.ControllerUtentiLocal;
import eccezioni.CampoErratoException;
import eccezioni.UtenteBannatoException;
import eccezioni.UtenteGiaRegistratoException;
import eccezioni.UtenteGiaVerificatoException;
import eccezioni.UtenteNonTrovatoException;
import entity.Adesione;
import entity.UtenteRegistrato;
import java.io.IOException;
import java.util.LinkedList;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.tanesha.recaptcha.ReCaptcha;
import net.tanesha.recaptcha.ReCaptchaFactory;
import net.tanesha.recaptcha.ReCaptchaResponse;
import statefulSB.UtenteLoggato.StatoIscrizione;
import statefulSB.UtenteLoggatoLocal;
import utilities.Regexp;
import utilities.Utilities;

/**
 * Servlet per la registrazione di un nuovo utente, sia tramite sito che social.
 * @author Luca Novara
 */
public class UserRegistrationServlet extends HttpServlet {
    @EJB
    private ControllerProfiloLocal controllerProfilo;

    @EJB
    private ControllerUserRegistrationLocal controllerUserRegistration;
    @EJB
    private ControllerMailLocal controllerMail;
    @EJB
    private ControllerUtentiLocal controllerUtenti;
    private static final String RECAPTCHA_PRIVATE_KEY = "6LefcscSAAAAACNpi1dCi4RQn14Vwh3syoAWTLAS";
    private static final String RECAPTCHA_PUBLIC_KEY = "6LefcscSAAAAAB3U-OspGUnvwBE2IGSSDqWNAT82";

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        String action = request.getParameter("action");

        if (action == null) {
            Utilities.errore("Nessuna action specificata alla UserRegistrationServlet", request, response);
        } else if (action.equals("mostraRegistrazionePopup")) { //richiesta ajax
            mostraRegistrazionePopup(request, response);
        } else if (action.equals("mostraRegistrazioneUtenteSito")) {
            mostraRegistrazioneUtenteSito(request, response);
        } else if (action.equals("mostraDimenticataPasswordPopup")) {
            mostraDimenticataPasswordPopup(request, response);
        } else if (action.equals("utenteEsistente")) {
            utenteEsistente(request, response);
        } else if (action.equals("forgetPassword") || action.equals("changePassword") || action.equals("mailPassword")) {
            forgetPassword(request, response);
        } else if (action.equals("validateUser")) {
            validateUser(request, response);
        } else if (action.equals("registerUser")) {
            registerUser(request, response);
        }

    }

    private void forgetPassword(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String action = request.getParameter("action");
        if (action == null) {
            Utilities.errore("Stringa di riconoscimento non valida.", request, response);
        }
        if (action.equals("forgetPassword")) {
            String email = request.getParameter("email");
            UtenteRegistrato ur = controllerUtenti.getUserByMail(email);
            if (ur == null) {
                Utilities.errore("Non risulti registrato.", request, response);
                return;
            } else {
                controllerUserRegistration.changeUUID(UUID.randomUUID().toString(), ur);
                controllerMail.sendMailPwd(ur);
                request.setAttribute("nome", ur.getNome());
                request.setAttribute("mail", ur.getEmail().getIndirizzo());
                Utilities.forward("/cambiaPasswordMailMandata.jsp", request, response);
                return;
            }
        } else if (action.equals("changePassword")) {
            String id = request.getParameter("id");
            UtenteRegistrato ur = controllerUtenti.getUtenteById(Long.parseLong(id));
            String pwd = request.getParameter("password");
            String pwd2 = request.getParameter("password2");
            String errori = "";
            if (!Regexp.checkPassword(pwd, true)) {
                errori += "<li>" + "la password deve essere compresa tra 8 e 32 caratteri</li>";
            }
            if (!Regexp.checkPasswordCoincidence(pwd, pwd2, true)) {
                errori += "<li>" + "le password non coincidono</li>";
            }
            if (!"".equals(errori)) {
                request.setAttribute("utente", ur);
                request.setAttribute("errore", errori);
                Utilities.forward("/cambiaPassword.jsp", request, response);
            }
            ur.setCrittoPassword(pwd);
            controllerUserRegistration.changeUUID(null, ur);
            request.setAttribute("pwModificata", true);
            Utilities.forward("/index.jsp", request, response);
            return;
        } else if (action.equals("mailPassword")) {
            String uuid = request.getParameter("pwdId");
            String id = request.getParameter("id");
            if (uuid != null && id != null) {
                UtenteRegistrato ur = controllerUtenti.getUtenteById(Long.parseLong(id));
                if (ur.getUuid().equals(uuid)) {
                    request.setAttribute("utente", ur);
                    Utilities.forward("/cambiaPassword.jsp", request, response);
                } else {
                    Utilities.errore("Stringa di riconoscimento non valida.", request, response);
                }
            } else {
                Utilities.errore("Stringa di riconoscimento non valida.", request, response);
            }
        }

    }

    private void registerUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String uid = request.getParameter("uid");
        if (uid != null) {
            validateUser(request, response);
        }
        ReCaptcha captcha;
        ReCaptchaResponse reCaptchaResponse;
        String address, id, mail, name, password, password2, phone, surname, paypal;
        boolean site;
        String captchaChallenge, captchaResponse, remoteAddr;

        name = request.getParameter("nome");
        surname = request.getParameter("cognome");
        address = request.getParameter("indirizzo");
        id = request.getParameter("id");
        mail = request.getParameter("mail");
        password = request.getParameter("password");
        password2 = request.getParameter("password2");
        phone = request.getParameter("telefono");
        paypal = request.getParameter("paypal");

        //true iff the request comes from registrazioneUtenteSito
        //useful in case of errors
        site = "true".equals(request.getParameter("sito"));
        UtenteRegistrato ur;
        remoteAddr = request.getRemoteAddr();
        captcha = ReCaptchaFactory.newReCaptcha(RECAPTCHA_PUBLIC_KEY, RECAPTCHA_PRIVATE_KEY, false);

        captchaChallenge = request.getParameter("recaptcha_challenge_field");
        captchaResponse = request.getParameter("recaptcha_response_field");

        reCaptchaResponse = captcha.checkAnswer(remoteAddr, captchaChallenge, captchaResponse);

        if (reCaptchaResponse.isValid()) {
            try {
                //String mail, String password, String nome, String cognome, String indirizzo, String telefono
                ur = controllerUserRegistration.inserisciUtente(mail, password, password2, name, surname, address, phone, paypal, site);//di base non verificato
                if (id != null && !id.equals("null")) {
                    controllerProfilo.setFacebookId(ur, id);
                }
                controllerMail.sendMailVerifica(ur);

                request.setAttribute("nome", name);
                request.setAttribute("mail", mail);
                Utilities.forward("/utenteNonVerificato.jsp", request, response);
            } catch (UtenteBannatoException ex) {
                request.setAttribute("bannato", "true");
                showError(site, mail, name, surname, request, response);
            } catch (UtenteGiaRegistratoException ex) {
                request.setAttribute("giaregistrato", "true");
                showError(site, mail, name, surname, request, response);
            } catch (CampoErratoException ex) {
                request.setAttribute("errore", ex.getMessage());
                showError(site, mail, name, surname, request, response);
            }
        } else {
            request.setAttribute("errore", "<li>Hai sbagliato a ricopiare le parole. Riprova!</li>");
            showError(site, mail, name, surname, request, response);
        }
    }

    private void showError(boolean site, String mail, String name, String surname, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (site) {
            Utilities.forward("/registrazioneUtenteSito.jsp", request, response);
        } else {
            request.setAttribute("email", mail);
            request.setAttribute("nome", name);
            request.setAttribute("cognome", surname);
            Utilities.forward("/registrazioneUtenteSocial.jsp", request, response);
        }
    }

    private void validateUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session;
        String uid;
        UtenteRegistrato ur;
        UtenteLoggatoLocal ull;

        uid = request.getParameter("uid");
        try {
            ur = controllerUserRegistration.verifica(uid);

            ull = lookupUtenteLoggatoLocal();
            ull.setIdUtente(ur.getId());
            ull.setAdesioniInCorso(new LinkedList<Adesione>());
            ull.setStatoIscrizione(StatoIscrizione.NESSUNO);
            session = request.getSession();
            session.setAttribute("utenteLoggato", ull);
            request.setAttribute("benvenuto", true);
            if (ur.getFacebookId() != null) {
                Utilities.forward("/Controller?action=linkFb&redirect=/ShippingShareBisBis-war/index.jsp", request, response);
            } else {
                Utilities.forward("/index.jsp", request, response);
            }
        } catch (UtenteBannatoException ex) {
            Utilities.errore(ex.getMessage(), request, response);
        } catch (UtenteNonTrovatoException ex) {
            Utilities.errore(ex.getMessage(), request, response);
        } catch (UtenteGiaVerificatoException ugve) {
            Utilities.errore(ugve.getMessage(), request, response);
        }

    }

    private void mostraRegistrazioneUtenteSito(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Utilities.forward("/registrazioneUtenteSito.jsp", request, response);
    }

    private void mostraRegistrazionePopup(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Utilities.forward("/WEB-INF/html/registrazione.html", request, response);
    }

    private void mostraDimenticataPasswordPopup(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Utilities.forward("/WEB-INF/jspf/dimenticataPassword.jsp", request, response);
    }

    // ajax
    private void utenteEsistente(HttpServletRequest request, HttpServletResponse response) {
        String mail = request.getParameter("mail");
        boolean isReg = controllerUtenti.isRegistrato(mail);
        response.setContentType("text/xml");
        response.setHeader("Cache-Control", "no-cache");
        try {
            response.getWriter().write("<isRegistrato>" + isReg + "</isRegistrato>");
        } catch (IOException ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private UtenteLoggatoLocal lookupUtenteLoggatoLocal() {
        Context c;

        try {
            c = new InitialContext();
            return (UtenteLoggatoLocal) c.lookup("java:global/ShippingShareBisBis/ShippingShareBisBis-ejb/UtenteLoggato!statefulSB.UtenteLoggatoLocal");
        } catch (NamingException ne) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
            throw new RuntimeException(ne);
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
    
}
